package com.meshnetics.gb.stack.mac.util;

/**
 * Simple semaphor. Allows to "acquire" some tokens (request blocks thread untils needed amount of tokens become
 * released). Until semaphor is free (doesn't block a thread) it can't be used again. Other thread can release tokens
 * for blocked thread. When semaphor is not blocked - all release calls are just ignored.
 *
 * @author AKovylin
 */
public class SimpleSemaphor {
    private int counter = 0;

    public void release() {
        release(1);
    }

    public void release(int count) {
        synchronized (this) {
            counter -= count;
            if (counter <= 0) {
                this.notify();
            }
        }
    }

    public void acquire(int counter) throws InterruptedException {
        synchronized (this) {
            if (this.counter > 0) {
                throw new IllegalStateException("locked");
            }
            this.counter = counter;
            while (this.counter > 0) {
                this.wait();
            }
        }
    }

    public void acquire(int counter, long timeout) throws InterruptedException {
        synchronized (this) {
            if (this.counter > 0) {
                throw new IllegalStateException("locked");
            }
            this.counter = counter;
            this.wait(timeout);
        }
    }

    public void unlock() {
        synchronized (this) {
            this.counter = 0;
            this.notify();
        }
    }

    public int getCounter() {
        synchronized (this) {
            return counter;
        }
    }

    public boolean isUnlocked() {
        synchronized (this) {
            return counter <= 0;
        }
    }
}
